package erfgame.core.graphics.renderer;

import java.util.HashMap;
import java.util.Map;


import erfgame.core.entity.Entity;
import erfgame.core.entity.EntityEvent;
import erfgame.core.entity.EntityEventType;
import erfgame.core.entity.EntityListener;
import erfgame.core.entity.State;
import erfgame.core.entity.StatefulEntity;
import erfgame.core.world.World;
import erfgame.core.world.WorldAwarePrototype;

public class StatefulEntityRenderer extends AbstractEntityRendererProxy
		implements EntityListener, PrototypeEntityRenderer {

	private StatefulEntity stateful;
	protected Map<State, EntityRenderer> renderers;
	protected EntityRenderer defaultRenderer;
	private EntityRenderer currentRenderer;
	protected World world;
	
	public StatefulEntityRenderer( 
			World world, 
			StatefulEntity stateful, 
			Map<State, EntityRenderer> renderers, 
			EntityRenderer defaultRenderer ) {
		this.world = world;
		this.stateful = stateful;
		this.defaultRenderer = defaultRenderer;
		this.renderers = renderers;
		//this.currentRenderer = getRenderer( stateful.getCurrentState() );
		setProxied(defaultRenderer);
	}
	
	public void entityChanged(Entity source, EntityEvent event) {
		
		State state = stateful.getCurrentState();
		// TODO resize entity to fit renderer??
		EntityRenderer renderer = getRenderer( state );
		if( renderer != currentRenderer ) {
			// assume that the renderer can be safely reset (don't need to calculate offset)'		
			// TODO : some kind of abstraction around this
			if( renderer instanceof AnimatedEntityRenderer ) {
				((AnimatedEntityRenderer)renderer).resetCurrentIndex();
			}
			setProxied( renderer );
		}
	}
	
	public void reloadState() {
		EntityRenderer renderer = getRenderer( stateful.getCurrentState() );
		if( renderer != this.getProxied() ) {
			// TODO : some kind of abstraction around this
			if( renderer instanceof AnimatedEntityRenderer ) {
				((AnimatedEntityRenderer)renderer).updateRunDuration( (int)(world.getWorldTime() - stateful.getCurrentStateTime()) );
			}
			setProxied( renderer );
		}
	}
	
	
	public EntityRenderer getRenderer( State state ) {
		EntityRenderer currentRenderer = renderers.get( state );
		if( currentRenderer == null ) {
			currentRenderer = defaultRenderer;
		}
		return currentRenderer;
	}

	public void start() {
		reloadState();
		this.getEntity().addEntityListener(EntityEventType.state, this);
		super.start();
	}

	public void stop() {
		this.getEntity().removeEntityListener(EntityEventType.state, this);
		super.stop();
	}
	
	@SuppressWarnings("unchecked")
	public EntityRenderer spawn(World world, Entity entity) {
		EntityRenderer defaultRenderer = ((PrototypeEntityRenderer)this.defaultRenderer).spawn(world, entity);
		Map<State, EntityRenderer> renderers = new HashMap<State, EntityRenderer>( this.renderers.size() );
		for( Map.Entry<State, EntityRenderer> entry : this.renderers.entrySet() ) {
			renderers.put( entry.getKey(), ((WorldAwarePrototype<EntityRenderer>)entry.getValue()).spawn(world) );
		}
		StatefulEntityRenderer result = new StatefulEntityRenderer(
				world, 
				this.stateful, 
				renderers, 
				defaultRenderer
		);
		return result;
	}

}
